package com.mb.ext.base;


import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.PagingAndSortingRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 *  其他service 需要基础该service
 * @author huangwl
 * @date 2018/11/20 9:56
 */

public abstract class BaseService<T> implements PagingAndSortingRepository<T,String> {

    abstract protected BaseRepository<T> getBaseRepository();



    @Override
    public Iterable<T> findAll(Sort sort) {
        return getBaseRepository().findAll(sort);
    }

    @Override
    public Page<T> findAll(Pageable pageable) {
        return getBaseRepository().findAll(pageable);
    }

    @Override
    public <S extends T> S save(S s) {
        return getBaseRepository().save(s);
    }

    @Override
    public <S extends T> Iterable<S> saveAll(Iterable<S> iterable) {
        return getBaseRepository().saveAll(iterable);
    }

    @Override
    public Optional<T> findById(String integer) {
        return getBaseRepository().findById(integer);
    }

    @Override
    public boolean existsById(String integer) {
        return getBaseRepository().existsById(integer);
    }

    @Override
    public Iterable<T> findAll() {
        return getBaseRepository().findAll();
    }

    @Override
    public Iterable<T> findAllById(Iterable<String> iterable) {
        return getBaseRepository().findAllById(iterable);
    }

    @Override
    public long count() {
        return getBaseRepository().count();
    }

    @Override
    public void deleteById(String integer) {
        getBaseRepository().deleteById(integer);
    }

    @Override
    public void delete(T t) {
        getBaseRepository().delete(t);
    }

    @Override
    public void deleteAll(Iterable<? extends T> iterable) {
        getBaseRepository().deleteAll(iterable);
    }

    @Override
    public void deleteAll() {
        getBaseRepository().deleteAll();
    }

    public List<HashMap<String,Object>> findBySql(EntityManager entityManager, String sql){
        Query nativeQuery = entityManager.createNativeQuery(sql);
        return nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();
    }

    public Object findSingleBySql(EntityManager entityManager, String sql){
        Query nativeQuery = entityManager.createNativeQuery(sql);
        return nativeQuery.getSingleResult();
    }

    public List<T> findObjectBySql(EntityManager entityManager, String sql, T t){
        Query nativeQuery = entityManager.createNativeQuery(sql);
        List<T> resultList = nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(t.getClass())).getResultList();
        return resultList;
    }

    public int updateBySql(EntityManager entityManager, String sql){
        Query nativeQuery = entityManager.createNativeQuery(sql);
        int i = nativeQuery.executeUpdate();
        return i;
    }

    public List<T> findObjectByHql(EntityManager entityManager, String hql, T t, HashMap<String,Object> params){
        Query query = entityManager.createQuery(hql,t.getClass());
        for (Map.Entry<String, Object> entry : params.entrySet()) {
//            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            query.setParameter(entry.getKey(),entry.getValue());
        }
        List<T> resultList = query.getResultList();
        return resultList;
    }

    public List<T> findObjectByHql(EntityManager entityManager, String hql, T t){
        Query query = entityManager.createQuery(hql,t.getClass());
        List<T> resultList = query.getResultList();
        return resultList;
    }

    /**
     *
     * @param entityManager
     * @param countSql 统计总条数sql
     * @param columnSql 查询sql
     * @param pageable
     * @param pageNum
     * @param pageSize
     * @return
     */
    public Page<HashMap<String,Object>> findPage(EntityManager entityManager, String countSql, String columnSql, Pageable pageable, Integer pageNum, Integer pageSize){
        Query nativeQuery = entityManager.createNativeQuery(countSql);
        Object singleResult = nativeQuery.getSingleResult();
        Query columnQuery = entityManager.createNativeQuery(columnSql);
        columnQuery.setFirstResult((pageNum-1)*pageSize);
        columnQuery.setMaxResults(pageSize);
        List resultList = columnQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();
        Page<HashMap<String,Object>> page=new PageImpl<>(resultList,pageable,Long.valueOf(singleResult.toString()));
        return page;
    }
}
